#pragma once
#include <zGraphicsConfig.hpp>
#include "Quaternion.hpp"
#include "Rotation.hpp"
#include "Translation.hpp"
#include "Transformation.hpp"

namespace zzz{
class ZGRAPHICS_CLASS ArcBall{
public:
  double win_w;  /// the windows
  double win_h;  /// the windows  
  double old_x;   /// stores the x coordinate where was pressed    
  double old_y;   /// stores the y coordinate where was pressed    
  Quaternion<double> anchor_rot; /// Anchors the current roration
  Quaternion<double> rot; /// Stores the current rotation
  Quaternion<double> comb; ///in order to combine rotations, for instance, world rotation + object rotation
  //Quaternion<double> anchorLookAt;  /// Anchors the camera's current rotation
  //Quaternion<double> currentLookAt; /// to compute the camera's rotation increment
  bool inv_rotate; /// flag to check if rotation is inverse or normal
  bool combine; /// flag to allow a rotation combination
  bool mode2d;
  GLTransformation<double> trans;
public:
  ArcBall();
  void SetWindowSize(double w, double h);
  void SetOldPos(double x, double y);
  void Rotate(double x, double y);
  void Reset();
  Vector<3,double> GetAxis();
  double GetAngle();
  const GLTransformation<double> &GetGLTransform() const;
  const double* GetGLRotateMatrix() const;
  void SetInverse(bool val);
  void CombineRotation(const Quaternion<double> &q);
  void StopCombineRotation();
  const Quaternion<double> GetQuaternion() const;
  void SetMode2D(bool val);
  bool GetMode2D();
  void ApplyGL() const;
private:
  /// anchors the current rotation
  void Bind();
  void Normalize(double &x, double &y);
  void ProjectOntoSurface(Vector<3,double> &v);
};
}
